Imports System
Imports System.ComponentModel
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports DevExpress.CodeRush.Core
Imports DevExpress.CodeRush.PlugInCore
Imports DevExpress.CodeRush.StructuralParser
Imports System.Collections

Namespace CR_FlowInfo
    ''' <summary>
    ''' Summary description for FlowInfoWindow.
    ''' </summary>
    <Guid("1922fe50-7ba9-4b5b-a9a5-26e4450424d7"), _
     Title("Flow Info")> _
    Public Class FlowInfoWindow
        Inherits ToolWindowPlugIn

#Region " private fields... "
        Friend WithEvents events_ As DevExpress.DXCore.PlugInCore.DXCoreEvents
        ''' <summary>
        ''' Required designer variable.
        ''' </summary>
        Private components As System.ComponentModel.IContainer
#End Region

        ' constructor...
#Region " FlowInfoWindow "
        Public Sub New()
            ' This call is required by the Windows.Forms Form Designer.
            InitializeComponent()
        End Sub
#End Region

        ' DXCore-generated code
#Region " InitializePlugIn "
        Public Overrides Sub InitializePlugIn()
            MyBase.InitializePlugIn()

            '
            ' TODO: Add your initialization code here.
            '
        End Sub
#End Region
#Region " FinalizePlugIn "
        Public Overrides Sub FinalizePlugIn()
            '
            ' TODO: Add your finalization code here.
            '

            MyBase.FinalizePlugIn()
        End Sub
#End Region

#Region " ShowWindow "
        ''' <summary>
        ''' Opens and displays this tool window. If the tool window is already open,
        ''' it will be focused.
        ''' </summary>
        Public Shared Function ShowWindow() As EnvDTE.Window
            Return DevExpress.CodeRush.Core.CodeRush.ToolWindows.Show(GetType(FlowInfoWindow).GUID)
        End Function
#End Region
#Region " HideWindow "
        ''' <summary>
        ''' Hides this tool window if it is open.
        ''' </summary>
        Public Shared Function HideWindow() As EnvDTE.Window
            Return DevExpress.CodeRush.Core.CodeRush.ToolWindows.Hide(GetType(FlowInfoWindow).GUID)
        End Function
#End Region

#Region " Instance "
        ''' <summary>
        ''' Returns the created instance of this tool window if it is open. If the tool window
        ''' is not open in Visual Studio, this property returns null.
        ''' </summary>
        Public Shared ReadOnly Property Instance() As FlowInfoWindow
            Get
                Return CType(DevExpress.CodeRush.Core.CodeRush.ToolWindows.GetPlugInControl(GetType(FlowInfoWindow)), FlowInfoWindow)
            End Get
        End Property
#End Region

#Region " Component Designer generated code "
        ''' <summary>
        ''' Required method for Designer support - do not modify
        ''' the contents of this method with the code editor.
        ''' </summary>
        Friend WithEvents flowTree As System.Windows.Forms.TreeView
        Private Sub InitializeComponent()
            Me.components = New System.ComponentModel.Container
            Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(FlowInfoWindow))
            Me.events_ = New DevExpress.DXCore.PlugInCore.DXCoreEvents(Me.components)
            Me.flowTree = New System.Windows.Forms.TreeView
            CType(Me.events_, System.ComponentModel.ISupportInitialize).BeginInit()
            CType(Me, System.ComponentModel.ISupportInitialize).BeginInit()
            Me.SuspendLayout()
            '
            'events_
            '
            '
            'flowTree
            '
            Me.flowTree.Dock = System.Windows.Forms.DockStyle.Fill
            Me.flowTree.ImageIndex = -1
            Me.flowTree.Location = New System.Drawing.Point(0, 0)
            Me.flowTree.Name = "flowTree"
            Me.flowTree.SelectedImageIndex = -1
            Me.flowTree.Size = New System.Drawing.Size(150, 150)
            Me.flowTree.TabIndex = 0
            '
            'FlowInfoWindow
            '
            Me.Controls.Add(Me.flowTree)
            Me.Image = CType(resources.GetObject("$this.Image"), System.Drawing.Bitmap)
            Me.ImageBackColor = System.Drawing.Color.FromArgb(CType(0, Byte), CType(255, Byte), CType(255, Byte), CType(255, Byte))
            Me.Name = "FlowInfoWindow"
            CType(Me.events_, System.ComponentModel.ISupportInitialize).EndInit()
            CType(Me, System.ComponentModel.ISupportInitialize).EndInit()
            Me.ResumeLayout(False)

        End Sub
#End Region

        ' protected methods...
#Region " Dispose "
        ''' <summary>
        ''' Clean up any resources being used.
        ''' </summary>
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If (disposing) Then
                If Not components Is Nothing Then
                    components.Dispose()
                End If
            End If

            MyBase.Dispose(disposing)
        End Sub
#End Region
        Private _prevLine As Integer

        Private Sub BuildTree()
            flowTree.Nodes.Clear()
            Dim nodes As New ArrayList
            Dim currDoc As TextDocument = CodeRush.Documents.ActiveTextDocument
            Dim levelsDeep As Integer
            Dim theNode As LanguageElement '=CodeRush.Source.Active
            dim strCurrentLine as string=currdoc.GetLine(coderush.Caret.Line)
            dim Offset as Integer=(strCurrentLine.Length - strCurrentLine.TrimStart.Length) + 1
            theNode = currDoc.GetNodeat(coderush.Caret.Line,offset)
            If Not theNode Is Nothing Then
                levelsDeep = theNode.LevelsDeep
            End If
            While Not TypeOf theNode Is [Property] AndAlso Not TypeOf theNode Is Method AndAlso Not theNode Is Nothing
                If TypeOf theNode Is DelimiterCapableBlock AndAlso DirectCast(theNode, DelimiterCapableBlock).HasDelimitedBlock AndAlso theNode.LevelsDeep < levelsDeep Then
                    nodes.Add(theNode)
                    levelsDeep = theNode.LevelsDeep
                End If
                theNode = theNode.PreviousNode
            End While
            If Not theNode Is Nothing Then
                nodes.Add(theNode)
            End If
            Dim parentnode As TreeNode
            For i As Integer = nodes.Count - 1 To 0 Step -1
                theNode = nodes(i)
                addnodetotree(thenode,currdoc,parentnode,True )
            Next
            If flowTree.Nodes.Count > 0 Then
                flowTree.Nodes(0).ExpandAll()
            End If
        End Sub
        Private Sub AddNodeToTree(ByVal theNode As LanguageElement, ByVal currDoc As TextDocument, ByRef parentnode As TreeNode, ByVal NewParent As Boolean)
            If TypeOf theNode Is [Else] OrElse TypeOf theNode Is [ElseIf] Then
                Dim prevNode As LanguageElement = theNode.PreviousCodeSibling
                AddNodeToTree(prevNode, currDoc, parentnode,False )
            End If
            Dim strNode As String = currDoc.GetLine(theNode.Range.Start.Line).Trim
            If parentnode Is Nothing Then
                parentnode = flowTree.Nodes.Add(strNode)
            Else
                If not NewParent Then
                    parentnode.Nodes.Add(strNode)
                Else
                    parentnode = parentnode.Nodes.Add(strNode)
                    
                End If
            End If
        End sub
        Private Sub events__AfterParse(ByVal ea As DevExpress.CodeRush.Core.AfterParseEventArgs) Handles events_.AfterParse
            Try
                BuildTree()
            Catch ex As Exception
                MessageBox.Show(ex.ToString)
            End Try
        End Sub

        Private Sub events__CaretMoved(ByVal ea As DevExpress.CodeRush.Core.CaretMovedEventArgs) Handles events_.CaretMoved
            Static PrevDocument As TextDocument
            Try
                Dim currDoc As TextDocument = CodeRush.Documents.ActiveTextDocument
                If Not currDoc Is Nothing Then
                    If Not PrevDocument Is currDoc Then
                        _prevLine = -1
                        PrevDocument = currDoc
                    End If
                    If _prevLine <> CodeRush.Caret.Line Then
                        _prevLine = CodeRush.Caret.Line
                        BuildTree()
                    End If
                Else
                    flowTree.Nodes.Clear()
                    Return
                End If
            Catch ex As Exception
                MessageBox.Show(ex.ToString)
            End Try
        End Sub
    End Class
End Namespace
